fix: resolve provider validation and CORS issues in dev mode#1759
Conversation
- Only validate explicitly added providers to prevent unnecessary connection attempts - Start periodic validation only for added providers - Watch for newly added providers and start their validation - Disable webSecurity in development mode to fix CORS errors with external APIs Fixes connection refused errors for Ollama/LM Studio when not running locally. Fixes CORS errors when using OpenAI-compatible APIs in development mode. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request disables webSecurity in development mode and updates the provider store to only perform periodic validation for explicitly added providers. The review feedback identifies a significant security risk in disabling webSecurity and a resource leak in the provider validation logic, as intervals are not cleared when a provider is removed.
| preload: join(dirname(fileURLToPath(import.meta.url)), '../preload/index.mjs'), | ||
| sandbox: false, | ||
| // Disable webSecurity in development to avoid CORS issues | ||
| webSecurity: !is.dev, |
There was a problem hiding this comment.
Disabling webSecurity is a significant security risk, even in development mode. It makes your application vulnerable to cross-site scripting (XSS) attacks if it loads any third-party content in the renderer. While convenient for bypassing CORS issues, a more secure and production-like approach is to proxy requests through the main process. The main process is not subject to CORS, so it can safely fetch data from external APIs and forward it to the renderer process via IPC. This keeps webSecurity enabled, hardening your app against potential vulnerabilities.
| watch(addedProviders, (newAdded, oldAdded) => { | ||
| for (const providerId of Object.keys(newAdded)) { | ||
| if (newAdded[providerId] && !oldAdded?.[providerId]) { | ||
| // Provider was just added, start its periodic validation if configured | ||
| const intervalMs = providerValidationIntervalMsById.get(providerId) | ||
| if (intervalMs && intervalMs > 0 && !providerRevalidationLoops.has(providerId)) { | ||
| const loop = useIntervalFn(() => { | ||
| void validateProvider(providerId, { force: true }) | ||
| }, intervalMs, { immediate: false, immediateCallback: false }) | ||
| loop.resume() | ||
| providerRevalidationLoops.set(providerId, loop) | ||
| } | ||
| } | ||
| } | ||
| }, { deep: true }) |
There was a problem hiding this comment.
This watch block only handles provider additions. When a provider is removed, its periodic validation interval continues to run, leading to a resource leak. You should also handle provider removal by stopping the corresponding interval. Note that broader refactoring for type safety should be addressed in a separate pull request to maintain a focused scope.
watch(addedProviders, (newAdded, oldAdded) => {
const allIds = new Set([...Object.keys(newAdded), ...Object.keys(oldAdded || {})]);
for (const providerId of allIds) {
const isNew = newAdded[providerId];
const wasOld = oldAdded?.[providerId];
if (isNew && !wasOld) {
// Provider was just added, start its periodic validation if configured
const intervalMs = providerValidationIntervalMsById.get(providerId);
if (intervalMs && intervalMs > 0 && !providerRevalidationLoops.has(providerId)) {
const loop = useIntervalFn(() => {
void validateProvider(providerId, { force: true });
}, intervalMs, { immediate: false, immediateCallback: false });
loop.resume();
providerRevalidationLoops.set(providerId, loop);
}
} else if (!isNew && wasOld) {
// Provider was removed, stop its periodic validation
const loop = providerRevalidationLoops.get(providerId);
if (loop) {
(loop as { pause: () => void }).pause();
providerRevalidationLoops.delete(providerId);
}
}
}
}, { deep: true })References
- Pull requests should have a focused scope. Broader refactoring, such as modifying shared interfaces for better type safety, should be addressed in a separate pull request to avoid scope creep.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 80560723da
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // Watch for newly added providers and start their periodic validation | ||
| watch(addedProviders, (newAdded, oldAdded) => { | ||
| for (const providerId of Object.keys(newAdded)) { | ||
| if (newAdded[providerId] && !oldAdded?.[providerId]) { |
There was a problem hiding this comment.
Detect added providers without comparing deep-watch old value
markProviderAdded() mutates addedProviders.value in place, and this watcher is deep: true, so on nested mutations Vue passes the same object for newAdded and oldAdded. That makes !oldAdded?.[providerId] false even when a key is newly inserted, so providers added after startup never enter this block and never get their periodic validation loop (contradicting the intended “watch newly added providers” behavior).
Useful? React with 👍 / 👎.
Fixes connection refused errors for Ollama/LM Studio when not running locally. Fixes CORS errors when using OpenAI-compatible APIs in development mode.
Description
Linked Issues
Additional Context